BackForward

/*----------------------------------------\
| Update the existing datasets;                                      |
|-------------------------------------------|
|--------------------------------------------------------------------|
|---------------------------|
| Arguments:                                                         |
|   indata  - input datasets, at least 2 datasets are required;      |
|   by      - key variables between the input datasets;              |
|             this is the key variables we need for merging the      |
|             datasets;                                              |
|             Note: these variables will be used as the complex keys;|
|   keep    - Keep the rows from which datasets;                     |
|   outdata - The output dataset;                                    |
|--------------------------------|
|--------------------------------------------------------------------|
|---------------------------------------|
| Example:                                                           |
|  %update(indata=ridcrf.ae ridcrf.ae1, by=pt aedt docnum, keep=1,   |
|          outdata=ae);                                              |
| Usgae: update(indata=,by=, keep=1, outdata=)/parmbuff;             |
\----------------------------------------*/
%macro update/parmbuff;
/*--------------------------------------------\
| Copy Right: Duo Zhou;                       |
| Created:  12-01-2002 1:54pm;                |
| Purpose:  update existing datasets;         |
\--------------------------------------------*/
%let _updatecnt_=0;
%let syspbuff=%sysfunc(translate(%quote(%substr(%quote(%trim(%quote(%left(%quote(&syspbuff))))), 2, %eval(%length(%trim(%quote(%left(%quote(&syspbuff)))))-2))), %str(%'), %str(%")));
%let indata=; %let by=; %let keep=; %let outdata=;
%do %while(%length(%nrbquote(%scan(%nrbquote(&syspbuff), %eval(&_updatecnt_+1), %nrbquote(,)))));
   %let _updatecnt_=%eval(&_updatecnt_+1);
   %let _udparam_=%nrbquote(%qscan(%nrbquote(&syspbuff), &_updatecnt_, %nrbquote(,)));
   %let _udparam1_=%trim(%left(%qscan(%nrbquote(&_udparam_), 1, %str(=))));
   %let _udparam2_=%substr(%quote(&_udparam_), %eval(%index(%quote(&_udparam_),%str(=))+1), %eval(%length(&_udparam_)-%index(%quote(&_udparam_),%str(=))));
   %if (not %index(%BQUOTE(%trim(%BQUOTE(%left(%BQUOTE(&_udparam_))))), %str(=))) %then %do;
      %if (%index(%BQUOTE(%trim(%BQUOTE(%left(%BQUOTE(&_udparam2_))))), %str(%()) eq 1) and
          (%index(%BQUOTE(%trim(%BQUOTE(%left(%BQUOTE(%sysfunc(reverse(&_udparam2_))))))), %str(%))) eq 1) %then
         %let _udparam2_=%substr(%quote(%trim(%quote(%left(%quote(&_udparam2_))))), 2, %eval(%length(%trim(%quote(%left(%quote(&_udparam2_)))))-2));
      %if (%quote(&_updatecnt_) = %quote(1)) %then %let indata=&_udparam2_; 
      %else %if (%quote(&_updatecnt_) = %quote(2)) %then %let by=&_udparam2_;
      %else %if (%quote(&_updatecnt_) = %quote(3)) %then %do;
         %if (%scan(&_udparam2_,1,1234567890)=) %then %let keep=&_udparam2_;
         %else %let keep=; 
      %end;
      %else %if (%quote(&_updatecnt_) = %quote(3)) %then %let outdata=&_udparam1_;
   %end;
   %else %if (%index(%BQUOTE(%trim(%BQUOTE(%left(%BQUOTE(&_udparam2_))))), %str(%()) eq 1) and
          (%index(%BQUOTE(%trim(%BQUOTE(%left(%BQUOTE(%sysfunc(reverse(&_udparam2_))))))), %str(%))) eq 1) %then 
      %let &_udparam1_=%substr(%quote(%trim(%quote(%left(%quote(&_udparam2_))))), 2, %eval(%length(%trim(%quote(%left(%quote(&_udparam2_)))))-2));
   %else %let &_udparam1_=&_udparam2_; 
%end;
/* By Variables */
%if (%quote(&by)=) %then %do;
   %put ==> Alert! Merging Variables are not given!;
   %goto finish;
%end;
%let _updatebnt_=0; %let _updatesqlby_=;
%do %while(%length(%nrbquote(%scan(%nrbquote(&by), %eval(&_updatebnt_+1), %nrbquote( ,)))));
   %let _updatebnt_=%eval(&_updatebnt_+1);
   %if (%quote(&_updatebnt_)=%quote(1)) %then %let _updatesqlby_=%nrbquote(%qscan(%nrbquote(&by), &_updatebnt_, %nrbquote( ,)));
   %else %let _updatesqlby_=%nrbquote(&_updatesqlby_), %nrbquote(%qscan(%nrbquote(&by), &_updatebnt_, %nrbquote( ,)));
%end;
/* Input Datasets */
%if (%quote(&indata)=) %then %do;
   %put ==> Alert! No Input dataset is provided!;
   %goto finish;
%end;
%else %if %index(&indata,.) = 0 %then %let indata=%upcase(work.&indata.);
%else %let indata=%upcase(&indata);
%let _updatednt_=0; %Let _updatenumdup_=0; %let _updatemergedata_=; %let _updatenvaliddata_=0;
%do %while(%length(%nrbquote(%scan(%nrbquote(&indata), %eval(&_updatednt_+1), %nrbquote( ,)))));
   %let _updatednt_=%eval(&_updatednt_+1);
   %let _updatedata_&_updatednt_=%nrbquote(%qscan(%nrbquote(&indata), &_updatednt_, %nrbquote( ,)));
   %if (%sysfunc(exist(&&_updatedata_&_updatednt_))) or (%sysfunc(exist(&&_updatedata_&_updatednt_, VIEW))) %then %do;
      %let _updatenvaliddata_=%eval(&_updatenvaliddata_+1); 
      options nonotes;
      proc sort data=&&_updatedata_&_updatednt_ out=_updatedata_&_updatednt_; by &by; run;
      options notes;
      %if (&_updatednt_ = 1) %then %do;
         %let _updatemergedata_=_updatedata_&_updatednt_ (in=in%trim(%left(&_updatednt_)));
         %put NOTE: There were %trim(%left(%nobs(_updatedata_&_updatednt_))) observations read from data set %trim(%left(%upcase(&&_updatedata_&_updatednt_))).;
      %end;
      %else %do;  
         %let _updatemergedata_=&_updatemergedata_ _updatedata_&_updatednt_ (in=in%trim(%left(&_updatednt_)));
         %put NOTE: There were %trim(%left(%nobs(_updatedata_&_updatednt_))) observations read from data set %trim(%left(%upcase(&&_updatedata_&_updatednt_))).;
      %end;
      options nonotes;
      proc sql;
         create table _updatetmp_%trim(%left(&_updatednt_)) as
         select *
         from &&_updatedata_&_updatednt_
         group by &_updatesqlby_
         having count(*)>1;
      %if (%nobs(_updatetmp_%trim(%left(&_updatednt_)))) %then %Let _updatenumdup_=&_updatenumdup_+1;
      proc datasets library=work nolist; delete _updatetmp_%trim(%left(&_updatednt_)); run;quit;
      options notes;
   %end;
%end; 
%if (&_updatenumdup_ >1) %then %do;
   %put ==> Alert! More than 1 dataset has duplicate records, this is many to many merge, update process failed!;
   %goto finish;
%end;
%if (&_updatednt_ < 2) %then %do;
   %put ==> Alert! Only 1 dataset is provided, dataset is not updated!;
   %goto finish;
%end;
%if (&_updatenvaliddata_ < 2) %then %do;
   %put ==> Alert! Only found 1 valid dataset, dataset is not updated!;
   %goto finish;
%end;
%if (%quote(&outdata) = ) %then %let outdata=&_updatedata_1;
%else %if %index(&outdata,.) = 0 %then %let outdata=%upcase(work.&outdata.);
%else %let outdata=%upcase(&outdata);
%if (%quote(&keep) ne) %then %do;
   %if (&keep < 1) or (&keep > &_updatednt_) %then %do;
      %put ==> Alert! Only %trim(%left(&_updatednt_)) datasets are found, I cannot find the dataset %trim(%left(&keep)).;
      %goto finish;
   %end;
%end;
options nonotes;
data &outdata;
   update &_updatemergedata_;
   by &by;
   %if (%quote(&keep) ne) %then if in%trim(%left(&keep));;
run;
proc sql;
   %do i=1 %to &_updatednt_; 
   %if (%sysfunc(exist(_updatedata_&i))) %then drop table _updatedata_&i;;
   %end;
quit;
options notes;
%put NOTE: There were %trim(%left(%nobs(&outdata))) observations write to data set %trim(%left(%upcase(&outdata))).;
%finish:
%mend update;